package checksum.test;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.Adler32;
import java.util.zip.CRC32;

public class Checksummer{

	
	
	public static void main(String[] args){
		try{
			System.out.println("Calculating checksums...");
			File dir = new File(".");
			StringBuffer outputBuffer = new StringBuffer();
			
//		 This filter only returns directories
			FilenameFilter fileFilter = new FilenameFilter() {
			    public boolean accept(File dir, String name) {
			        return name.indexOf(".") > -1;
			    }
			};

			
			String[] children = dir.list(fileFilter);
			if (children == null) {
			    System.out.println("No files match filter.");
			} else {
			    for (int i=0; i<children.length; i++) {
			        // Get filename of file or directory
			        String filename = children[i];
			        System.out.println(filename);
			        String checksum1 = calculateChecksum(filename);
			        String checksum2 = calculateChecksum(filename);
			        if(!checksum1.equals(checksum2)){
			        	//try again until it works.
			        	i--;
			        }
			        else
			        	outputBuffer.append(checksum1);
			    }
			    PrintWriter pw = new PrintWriter(new File("Checksums.txt"));
			    pw.write(outputBuffer.toString());
			    pw.close();
			}
		}catch(NoSuchAlgorithmException e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch(IOException e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

//	public static void downloadChecksums(String[] files){
//		int moduleCount = staleModules.size();
//		for(int i = 0; i < moduleCount; i++){
//			try{
//				properties = VersionFileReaderV2.getCurrentVersionProperties();
//				int retryCount = 0;
//				boolean checksumPass = false;
//				while(retryCount < RETRY_LIMIT && !checksumPass){
//					checksumPass = download(staleModules.get(i));
//					if(checksumPass){
//						System.out.println("Checksum passed.");
//					}else{
//						System.out.println("Checksum failed, retrying.");
//						retryCount++;
//					}
//				}
//				if(retryCount == RETRY_LIMIT){
//					System.out.println("Failure.  Retry limit reached (" + RETRY_LIMIT + ").");
//					deleteFailedDownload(staleModules.get(i));
//				}else{
//					FileOutputStream propsOut = new FileOutputStream(AutoUpdateConstants.CURRENT_VERSIONS_FILE);
//					properties.store(propsOut, "---Auto Update---");
//					propsOut.close();
//				}
//			}catch(NoSuchAlgorithmException e){
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}catch(IOException e){
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		}
//	}


	private static String calculateChecksum(String filename) throws IOException, NoSuchAlgorithmException{
		// start timing
		//long startMillis = System.currentTimeMillis();
		long timeAdler32 = 0L;
		long timeCRC32 = 0L;
		long timeMD5 = 0L;
		long timeSHA1 = 0L;
		long timeWrite = 0L;
		//long timeCalc = 0L;
		long timeRead = 0L;
		long start = 0L;
		//long startDload = 0L;
//		long currentDuration;
//		long sDur = startMillis;
//		long eDur;
//		long dur;
//		int startBytes = 0;

		File file = new File(filename);

		InputStream inStream = new FileInputStream(file);
		DataInputStream dis = new DataInputStream(new BufferedInputStream(inStream));
		//DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(module.getModuleFilename() + ".upd")));

		//DLoadProgress dlp = new DLoadProgress();

		MessageDigest checksumMD5 = MessageDigest.getInstance("MD5");
		MessageDigest checksumSHA1 = MessageDigest.getInstance("SHA-1");
		Adler32 checksumAdler32 = new Adler32();
		CRC32 checksumCRC32 = new CRC32();
		int bytesRead = 0;
		int totalBytes = 0;
		byte data[] = new byte[1024];
		start = System.currentTimeMillis();
		//startDload = start;
		//int prevProgress = 0;
		while((bytesRead = dis.read(data)) > -1){
			totalBytes += bytesRead;
			timeRead += (System.currentTimeMillis() - start);

			start = System.currentTimeMillis();
			//dos.write(data, 0, bytesRead);
			timeWrite += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumAdler32.update(data, 0, bytesRead);
			timeAdler32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumCRC32.update(data, 0, bytesRead);
			timeCRC32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumMD5.update(data, 0, bytesRead);
			timeMD5 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumSHA1.update(data, 0, bytesRead);
			timeSHA1 += (System.currentTimeMillis() - start);
//
//			start = System.currentTimeMillis();
//			int progress = Math.round((100f * totalBytes) / fileSize) / 2;
//
//			currentDuration = System.currentTimeMillis() - startMillis + 1;
//			double averageSpeed = 1 * totalBytes / currentDuration;
//
//			eDur = System.currentTimeMillis();
//			dur = eDur - sDur + 1;
//			double currentSpeed = 1 * (totalBytes - startBytes) / dur;
//			if(dur >= 5000d){
//				sDur += (dur / 2);
//				startBytes += ((totalBytes - startBytes) / 2);
//			}
//			dlp.setCurrentSpeed(currentSpeed);
//			dlp.setAverageSpeed(averageSpeed);
//			dlp.setProgress(progress);
//
//			while(progress > prevProgress){
//				System.out.print(".");
//				prevProgress++;
//			}
//
//			// System.out.println(totalBytes);
//			// System.out.println(progress);
//			// if(bytesRead == 0)
//			// System.out.println(bytesRead);
//
//			timeCalc += (System.currentTimeMillis() - start);

			start = System.currentTimeMillis();
		}
		//System.out.println();
		//properties.setProperty(module.getModuleName(), module.toString());

		start = System.currentTimeMillis();
		String resultMD5 = "";
		data = checksumMD5.digest();
		for(int i = 0; i < data.length; i++){
			resultMD5 += Integer.toString((data[i] & 0xff) + 0x100, 16).substring(1);
		}
		timeMD5 += (System.currentTimeMillis() - start);

		start = System.currentTimeMillis();
		String resultSHA1 = "";
		data = checksumSHA1.digest();
		for(int i = 0; i < data.length; i++){
			resultSHA1 += Integer.toString((data[i] & 0xff) + 0x100, 16).substring(1);
		}
		timeSHA1 += (System.currentTimeMillis() - start);

//		System.out.println("Bytes:\t\t" + totalBytes);
//		System.out.println("Adler32:\t" + timeAdler32 + "ms\t" + checksumAdler32.getValue());
//		System.out.println("CRC32:\t\t" + timeCRC32 + "ms\t" + checksumCRC32.getValue());
//		System.out.println("MD5:\t\t" + timeMD5 + "ms\t" + resultMD5);
//		System.out.println("SHA1:\t\t" + timeSHA1 + "ms\t" + resultSHA1);
//		System.out.println("Read:\t\t" + timeRead + "ms\t");
//		System.out.println("Write:\t\t" + timeWrite + "ms\t");
//		System.out.println("Calc:\t\t" + timeCalc + "ms\t");
//		long waste = (System.currentTimeMillis() - startDload) - (timeAdler32 + timeCRC32 + timeMD5 + timeSHA1 + timeRead + timeWrite + timeCalc);
//		System.out.println("Waste:\t\t" + waste + "ms\t");
		
		StringBuffer checksumStrBuf = new StringBuffer();
		checksumStrBuf.append("File:\t\t" + filename + "\r\n");
		checksumStrBuf.append("Adler32:\t" + checksumAdler32.getValue() + "\r\n");
		checksumStrBuf.append("CRC32:\t\t" + checksumCRC32.getValue() + "\r\n");
		checksumStrBuf.append("MD5:\t\t" + resultMD5 + "\r\n");
		checksumStrBuf.append("SHA1:\t\t" + resultSHA1 + "\r\n");
		checksumStrBuf.append("\r\n");

		//dos.flush();
		//dos.close();
		dis.close();

		// End timing
		//System.out.println((System.currentTimeMillis() - startMillis) + "ms");

		return checksumStrBuf.toString();
	}
}
